// src/timer/SafeTimer.test.ts

import dayjs from 'dayjs';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { setTimer } from '#lib';

// import { advanceTimersByTimeAsync } from '@liuli-util/test-lib' // 假设使用现代测试工具

vi.mock('dayjs', () => dayjs);

describe('SafeTimer 防止内存泄漏的定时器', () => {
  beforeEach(() => {
    // Using real timers for this test environment
  });

  afterEach(() => {
    // Cleanup handled by individual tests
  });

  it('基础：每 1 秒执行一次，立即执行', async () => {
    const fn = vi.fn();
    const timer = setTimer(1, 'second', fn, true);

    expect(fn).toHaveBeenCalledTimes(1);

    await new Promise((resolve) => setTimeout(resolve, 1100));
    expect(fn).toHaveBeenCalledTimes(2);

    await new Promise((resolve) => setTimeout(resolve, 1100));
    expect(fn).toHaveBeenCalledTimes(3);

    await new Promise((resolve) => setTimeout(resolve, 1100));
    expect(fn).toHaveBeenCalledTimes(4);

    timer.destroy();
  });

  it('支持 pause / resume 精确恢复剩余时间', async () => {
    const fn = vi.fn();
    const timer = setTimer(3, 'second', fn);

    // 等待1.5秒后暂停
    await new Promise((resolve) => setTimeout(resolve, 1500));
    timer.pause();

    // 暂停期间不应该继续执行
    await new Promise((resolve) => setTimeout(resolve, 1000));
    expect(fn).toHaveBeenCalledTimes(0);

    // 恢复后应该在大约1.5秒后执行
    timer.resume();
    await new Promise((resolve) => setTimeout(resolve, 1600));
    expect(fn).toHaveBeenCalledTimes(1);

    timer.destroy();
  });

  it('destroy 彻底清理，防止内存泄漏', async () => {
    const fn = vi.fn();
    const timer = setTimer(100, 1, fn);

    await new Promise((resolve) => setTimeout(resolve, 150));
    expect(fn).toHaveBeenCalledTimes(1);

    timer.destroy();

    await new Promise((resolve) => setTimeout(resolve, 200));
    expect(fn).toHaveBeenCalledTimes(1); // 不再继续执行
  });

  it('restart 可重启并可选立即执行', async () => {
    const fn = vi.fn();
    const timer = setTimer(500, 1, fn);

    await new Promise((resolve) => setTimeout(resolve, 600));
    expect(fn).toHaveBeenCalledTimes(1);

    timer.restart(true);
    expect(fn).toHaveBeenCalledTimes(2); // 立即执行一次

    await new Promise((resolve) => setTimeout(resolve, 600));
    expect(fn).toHaveBeenCalledTimes(3);

    timer.destroy();
  });

  it('支持直接传入毫秒数', async () => {
    const fn = vi.fn();
    const timer = setTimer(200, 1, fn, true); // 1 代表毫秒单位

    await new Promise((resolve) => setTimeout(resolve, 250));
    expect(fn).toHaveBeenCalledTimes(2);

    timer.destroy();
  });
});
